﻿using LoongCAD.STC.Friendly.Plugins;
using LoongCAD.STC.Friendly.Scene;
using LoongCAD.Geometry.Friendly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LoongCAD.STC.Friendly.DataType;
using LoongCAD.STC.Friendly.Scene.UI;

namespace DetailDemo
{
    //============组件通用属性=============
    [Plugin("DetailDemo")]                              //组件名称
    [PluginUserInterface("Form_PluginMain")]            //组件窗口类名称
    [PluginNumber(9998)]                                //组件编号
    //============细部组件属性===========
    [PluginRefPoint(true)]                              //是否需要辅助点
    public class DetailDemo : DetailPlugin
    {
        //当前创建的组件实例
        Detail comp;
        //组件窗口传入参数
        StructuresData data;
        //用户输入参数
        Beam mainPart;
        //自己建立的坐标系
        Matrix refMat;

        //=======创建过程相关的参数=========

        double colHeight = 0.0;
        double colWebThickness = 0.0;

        public DetailDemo(StructuresData data)
        { 
            this.data = data;
        }


        public override bool Run(Detail componentObject)
        {
            comp = componentObject;
            mainPart = comp.PrimaryObject as Beam;

            //计算参数
            CalcParams();
            //设置当前工作平面，之后的所有的几何数据(点，向量等)都会以这个工作平面为基准
            comp.Scene.SetCurrentTransformationPlane(new TransformationPlane(refMat));
            //创建对齐面
            CreateFitting();
            //创建底板
            CreateBasePlate();
            //创建加劲板
            CreateStiff();
            //创建抗剪键
            CreateShear();
            //将当前工作平面还原
            refMat.Inverse();
            comp.Scene.SetCurrentTransformationPlane(new TransformationPlane(refMat));
            return true;
        }


        void CalcParams()
        {
            //向程序发送查询数据指令，保证当前对象数据的实时性
            comp.Select();
            mainPart.Select();
            Point refPoint = comp.ReferancePoint;
            //建立坐标系
            { 
                List<Point> points = mainPart.GetCenterLine(false);
                Line mainLine = new Line(points[0], points[1]);
                Vector mainDir = points[1] - points[0];
                mainDir.Normalize();

                Plane p = new Plane(refPoint, mainDir);
                p.Intersect(mainLine, out Point intersetPoint);

                Point origin = intersetPoint;
                Point zDirPoint = points[0];
                if (points[0].Dist(origin) < points[1].Dist(origin))zDirPoint = points[1];
                Vector aixsZ = zDirPoint - origin;
                aixsZ.Normalize();

                CoordinateSystem coord = mainPart.GetCoordinateSystem();
                Vector aixsY = coord.AxisY;
                Vector aixsX = aixsY.Cross(aixsZ);

                refMat = new Matrix(origin, aixsX, aixsY, aixsZ);

#if DEBUG
                CreateAssistCoord(aixsX, aixsY, aixsZ, origin);
#endif
            }

            //计算截面数据
            {
                mainPart.GetReportProperty(PartReportProperties.PROFILE_HEIGHT, out colHeight);
                mainPart.GetReportProperty(PartReportProperties.PROFILE_WEB_THICKNESS, out colWebThickness);
            }


        }

        //绘制创建的坐标系
        void CreateAssistCoord(Vector dirX, Vector dirY, Vector dirZ, Point p0, double len = 1000)
        {
            //O
            ControlPoint cp = new ControlPoint();
            cp.Point = new Point(p0);
            cp.Insert();

            //X
            ControlLine x = new ControlLine();
            x.Line = new LineSegment(new Point(p0), new Point(p0 + dirX * len));
            x.Color = new Color(1.0, 0.0, 0.0);
            x.Extension = 100;
            x.Insert();
            //y
            ControlLine y = new ControlLine();
            y.Line = new LineSegment(new Point(p0), new Point(p0 + dirY * len));
            y.Color = new Color(0.0, 1.0, 0.0);
            y.Extension = 100;
            y.Insert();
            //z
            ControlLine z = new ControlLine();
            z.Line = new LineSegment(new Point(p0), new Point(p0 + dirZ * len));
            z.Color = new Color(0.0, 0.0, 1.0);
            z.Extension = 100;
            z.Insert();
        }


        void CreateFitting()
        { 
            Fitting fit = new Fitting();
            fit.CutTarget = mainPart;
            fit.Plane = new Plane(Vector.ZERO, Vector.AXIS_Z);
            fit.Insert();
        }

        void CreateBasePlate()
        {
            double thickness = data.plateProps.Thickness;
            double width = data.plateProps.Width;
            double height = data.plateProps.Height;
            //计算板的控制点位置
            Point p0 = new Point(0, 0, -thickness / 2);
            Point p1 = p0 + Vector.AXIS_X * (width / 2);
            p1 = p1 + Vector.AXIS_Y * (height / 2);
            Point p2 = p1 - Vector.AXIS_X * (width);
            Point p3 = p2 - Vector.AXIS_Y * (height);
            Point p4 = p3 + Vector.AXIS_X * (width);

            //=======创建板并设置属性========
            ContourPlate plate = new ContourPlate();
            //板的控制点(会随工作平面变化而变化)
            //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
            ContourPoint cp1 = new ContourPoint(p1, new Chamfer());
            ContourPoint cp2 = new ContourPoint(p2, new Chamfer());
            ContourPoint cp3 = new ContourPoint(p3, new Chamfer());
            ContourPoint cp4 = new ContourPoint(p4, new Chamfer());
            plate.AddContourPoint(cp1);
            plate.AddContourPoint(cp2);
            plate.AddContourPoint(cp3);
            plate.AddContourPoint(cp4);
            //板的空间位置属性(会随工作平面变化而变化）
            //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
            plate.Position.Depth = Position.DepthEnum.MIDDLE;
            plate.Position.DepthOffset = 0;

            //板的业务逻辑属性
            plate.Profile.ProfileString = "PL" + thickness;
            plate.Class = "7";
            plate.Material.MaterialString = data.plateProps.Material;
            plate.Name = data.plateProps.Name;
            plate.PartNumber.Prefix = data.plateProps.NoPrefix;
            //向程序发送创建指令
            plate.Insert();

            CreateWeld(mainPart, plate);
        }

        void CreateStiff()
        {
            double thickness = data.stiffProps.Thickness;
            double width = data.stiffProps.Width;
            double height = data.stiffProps.Height;
            
            void CreateOneStiff(Vector dir, double moveDist)
            {
                Point p = new Point(0, 0, 0);

                Point p1 = p + dir * moveDist;
                Point p2 = p1 + dir * width;
                Point p3 = p2 + Vector.AXIS_Z * height;
                Point p4 = p1 + Vector.AXIS_Z * height;

                //=======创建板并设置属性========
                ContourPlate stiff = new ContourPlate();
                //板的控制点(会随工作平面变化而变化)
                //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
                ContourPoint cp1 = new ContourPoint(p1, new Chamfer());
                ContourPoint cp2 = new ContourPoint(p2, new Chamfer());
                ContourPoint cp3 = new ContourPoint(p3, new Chamfer());
                ContourPoint cp4 = new ContourPoint(p4, new Chamfer());
                //设置倒角属性
                SetChamfer(cp1, data.chamferType, data.chamferX, data.chamferY, true);
                stiff.AddContourPoint(cp1);
                stiff.AddContourPoint(cp2);
                stiff.AddContourPoint(cp3);
                stiff.AddContourPoint(cp4);

                //板的空间位置属性(会随工作平面变化而变化）
                //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
                stiff.Position.Depth = Position.DepthEnum.MIDDLE;
                stiff.Position.DepthOffset = 0;

                //板的业务逻辑属性
                stiff.Profile.ProfileString = "PL" + thickness;
                stiff.Class = "7";
                stiff.Material.MaterialString = data.stiffProps.Material;
                stiff.Name = data.stiffProps.Name;
                stiff.PartNumber.Prefix = data.stiffProps.NoPrefix;
                //向程序发送创建指令
                stiff.Insert();

                CreateWeld(mainPart, stiff);
            }

            //创建+Y方向加劲
            CreateOneStiff(Vector.AXIS_Y, colHeight / 2);
            //创建-Y方向加劲
            CreateOneStiff(-Vector.AXIS_Y, colHeight / 2);
            //创建+X方向加劲
            CreateOneStiff(Vector.AXIS_X, colWebThickness / 2);
            //创建-X方向加劲
            CreateOneStiff(-Vector.AXIS_X, colWebThickness / 2);
        }
        void CreateShear()
        { 
            double basePlateThickness = data.plateProps.Thickness;
            Point p0 = new Point(0, 0, -basePlateThickness);
            Point p1 = p0;
            Point p2 = p1 - Vector.AXIS_Z * (150.0);
            //=======创建梁并设置属性========
            Beam beam = new Beam();
            //梁的控制点(会随工作平面变化而变化)
            //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
            beam.StartPoint = p1;
            beam.EndPoint = p2;
            //梁的空间位置属性(会随工作平面变化而变化）
            //当工作平面变化时，需要调用对象的Select()函数来获取它在当前工作平面下的位置属性
            beam.Position.Depth = Position.DepthEnum.MIDDLE;
            beam.Position.DepthOffset = 0;
            beam.Position.Rotation = Position.RotationEnum.TOP;
            beam.Position.RotationOffset = 0;
            beam.Position.Plane = Position.PlaneEnum.MIDDLE;
            beam.Position.PlaneOffset = 0;
            //梁的业务逻辑属性
            beam.Profile.ProfileString = data.beamProps.Profile;
            beam.PartNumber.Prefix = data.beamProps.NoPrefix;
            beam.Name = data.beamProps.Name;
            beam.Material.MaterialString = data.beamProps.Material;
            beam.Class = "7";
            //向主程序发送创建指令
            beam.Insert();

            CreateWeld(mainPart, beam);
        }

        /// <summary>
        /// 设置倒角属性
        /// </summary>
        /// <param name="cp"></param>
        /// <param name="type"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="reverse"></param>
        void SetChamfer(ContourPoint cp, int type, double x, double y, bool reverse = false)
        {
            switch (type)
            {
                case 0:
                case 2:
                    cp.Chamfer.Type = Chamfer.ChamferTypeEnum.CHAMFER_LINE;
                    cp.Chamfer.X = x;
                    cp.Chamfer.Y = y;
                    if (reverse)
                    { 
                        cp.Chamfer.X = y;
                        cp.Chamfer.Y = x;                    
                    }
                    break;
                case 1:
                    cp.Chamfer.Type = Chamfer.ChamferTypeEnum.CHAMFER_NONE;
                    cp.Chamfer.X = 0.0;
                    cp.Chamfer.Y = 0.0;
                    break;
                case 3:
                    cp.Chamfer.Type = Chamfer.ChamferTypeEnum.CHAMFER_ROUNDING;
                    cp.Chamfer.X = x;
                    cp.Chamfer.Y = x;
                    break;
                case 4:
                    cp.Chamfer.Type = Chamfer.ChamferTypeEnum.CHAMFER_ARC;
                    cp.Chamfer.X = x;
                    cp.Chamfer.Y = x;
                    break;
            }
        }

        /// <summary>
        /// 创建焊缝
        /// </summary>
        /// <param name="mainPart">主零件</param>
        /// <param name="subPart">次零件</param>
        /// <param name="pos">自动探测方向</param>
        void CreateWeld(Part mainPart, Part subPart, Weld.WeldPositionEnum pos = BaseWeld.WeldPositionEnum.WELD_POSITION_PLUS_X)
        {
            Weld w = new Weld();
            //指定主次零件
            w.MainObject = mainPart;
            w.SecondaryObject = subPart;
            //指定自动探测方向
            w.Position = pos;
            //如果有需要可添加焊缝的业务逻辑属性

            //向程序发送创建指令
            w.Insert();
        }
    }
}
